Typical HAL CORDIC use cases for migration

This section provides information about typical HAL CORDIC use cases for migration.

HAL CORDIC calculation use cases

Note

The calculation sequence using the HAL CORDIC driver is similar between HAL1 and HAL2:

  • Initialization, configuration, and starting the calculation in four modes: polling, zero-overhead, interrupt, and DMA.

  • For DMA:

    • In HAL1, the user specifies how to handle the input and output data (using the HAL CORDIC driver) or delegates it to another HAL driver (for example, HAL ADC).

    • In HAL2, the user can either use:

      • The function HAL_CORDIC_Calculate_DMA(). In this case, the input and output data are managed by the HAL CORDIC driver.

      • The functions HAL_CORDIC_Write_DMA() and HAL_CORDIC_Read_DMA() to individually control the CORDIC data streams for write and read directions. In this case, if the read or write should be managed by another peripheral (for example, ADC), the corresponding HAL CORDIC function (read/write) should be called.

For more details, see HAL CORDIC control functions migration.

Use case: HAL CORDIC calculate in polling / zero-overhead mode

Sequence diagram

CORDIC calculation in polling / zero-overhead mode

  @startuml

  participant "User application\n(thread mode)" as appli
  participant "<b>HAL CORDIC</b>" as cordic

  == Initialization / configuration ==
  appli -> cordic : HAL_CORDIC_Init(&hcordic)
  appli -> cordic : HAL_CORDIC_Configure(&hcordic, &cordic_config)

  == Calculation ==
  appli -> cordic : HAL_CORDIC_Calculate(&hcordic, input_data, output_data, n, timeout)\n/ HAL_CORDIC_CalculateZO(...)
  cordic --> appli : HAL status

  @enduml

Code snippet

HAL1

HAL2

#define INPUT_BUFFER_SIZE 4U
#define OUTPUT_BUFFER_SIZE 4U

int32_t input_data[INPUT_BUFFER_SIZE] =  {0x80000000, 0x90000000, 0xA0000000, 0xB0000000};
int32_t output_data[OUTPUT_BUFFER_SIZE] = {0U};










CORDIC_HandleTypeDef hcordic;
CORDIC_ConfigTypeDef cordic_config;

hcordic.Instance = CORDIC;
HAL_CORDIC_Init(&hcordic);



cordic_config.Function         = CORDIC_FUNCTION_SINE;
cordic_config.Precision        = CORDIC_PRECISION_6CYCLES;
cordic_config.Scale            = CORDIC_SCALE_0;
cordic_config.NbWrite          = CORDIC_NBWRITE_1;
cordic_config.NbRead           = CORDIC_NBREAD_1;
cordic_config.InSize           = CORDIC_INSIZE_32BITS;
cordic_config.OutSize          = CORDIC_OUTSIZE_32BITS;

HAL_CORDIC_Configure(&hcordic, &cordic_config)

HAL_CORDIC_Calculate(&hcordic, input_data, output_data, 4, 10);
/* OR */
HAL_CORDIC_CalculateZO(&hcordic, input_data, output_data, 4, 10);
#define INPUT_BUFFER_SIZE 4U
#define OUTPUT_BUFFER_SIZE 4U

int32_t input_data[INPUT_BUFFER_SIZE] =  {0x80000000, 0x90000000, 0xA0000000, 0xB0000000};
int32_t output_data[OUTPUT_BUFFER_SIZE] = {0U};

hal_cordic_buffer_desc_t input_buffer = {
    .p_data = input_data,
    .size_word = INPUT_BUFFER_SIZE};

hal_cordic_buffer_desc_t output_buffer = {
    .p_data = output_data,
    .size_word = OUTPUT_BUFFER_SIZE};

hal_cordic_handle_t hcordic;
hal_cordic_config_t cordic_config;


HAL_CORDIC_Init(&hcordic, HAL_CORDIC);

HAL_RCC_CORDIC_EnableClock();

cordic_config.function   = HAL_CORDIC_FUNCTION_SINE;
cordic_config.precision  = HAL_CORDIC_PRECISION_6_CYCLE;
cordic_config.scaling_factor = HAL_CORDIC_SCALING_FACTOR_0;
cordic_config.nb_args    = HAL_CORDIC_NB_ARG_1;
cordic_config.nb_results = HAL_CORDIC_NB_RESULT_1;
cordic_config.in_width    = HAL_CORDIC_IN_WIDTH_32_BIT;
cordic_config.out_width   = HAL_CORDIC_OUT_WIDTH_32_BIT;

HAL_CORDIC_SetConfig(&hcordic,&cordic_config);

HAL_CORDIC_Calculate(&hcordic, &input_buffer, &output_buffer, 10);
/* OR */
HAL_CORDIC_CalculateZeroOverhead(&hcordic, &input_buffer, &output_buffer, 10);

Key changes

  1. HAL2 uses buffer descriptors (hal_cordic_buffer_desc_t) instead of raw pointers and element counts.

  2. HAL2 updates the API naming and signatures: HAL_CORDIC_Configure() becomes HAL_CORDIC_SetConfig(), and HAL_CORDIC_CalculateZO() becomes HAL_CORDIC_CalculateZeroOverhead().

  3. HAL2 explicitly enables the peripheral clock using HAL_RCC_CORDIC_EnableClock().

Use case: HAL CORDIC calculate in interrupt mode

Sequence diagram

CORDIC calculation in interrupt mode

  @startuml

  participant "User application\n(thread mode)" as appli
  participant "<b>HAL CORDIC</b>" as cordic
  participant "CORDIC IRQ handler" as isr

  == Initialization / configuration ==
  appli -> cordic : HAL_CORDIC_Init(&hcordic)
  appli -> cordic : HAL_CORDIC_Configure(&hcordic, &cordic_config)
  appli -> appli : HAL_NVIC_SetPriority(CORDIC_IRQn, ...)
  appli -> appli : HAL_NVIC_EnableIRQ(CORDIC_IRQn)

  == Calculation ==
  appli -> cordic : HAL_CORDIC_Calculate_IT(&hcordic, input_data, output_data, n)
  cordic --> appli : HAL status

  == IRQ / callback ==
  isr -> cordic : CORDIC_IRQHandler()\nHAL_CORDIC_IRQHandler(&hcordic)
  cordic -> appli : HAL_CORDIC_CalculateCpltCallback(&hcordic)

  @enduml

Code snippet

HAL1

HAL2

#define INPUT_BUFFER_SIZE 4U
#define OUTPUT_BUFFER_SIZE 4U

int32_t input_data[INPUT_BUFFER_SIZE] =  {0x80000000, 0x90000000, 0xA0000000, 0xB0000000};
int32_t output_data[OUTPUT_BUFFER_SIZE] = {0U};









CORDIC_HandleTypeDef hcordic;
CORDIC_ConfigTypeDef cordic_config;

hcordic.Instance = CORDIC;
HAL_CORDIC_Init(&hcordic);

__HAL_RCC_CORDIC_CLK_ENABLE();

cordic_config.Function         = CORDIC_FUNCTION_SINE;
cordic_config.Precision        = CORDIC_PRECISION_6CYCLES;
cordic_config.Scale            = CORDIC_SCALE_0;
cordic_config.NbWrite          = CORDIC_NBWRITE_1;
cordic_config.NbRead           = CORDIC_NBREAD_1;
cordic_config.InSize           = CORDIC_INSIZE_32BITS;
cordic_config.OutSize          = CORDIC_OUTSIZE_32BITS;

HAL_CORDIC_Configure(&hcordic, &cordic_config)

HAL_NVIC_SetPriority(CORDIC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CORDIC_IRQn);

HAL_CORDIC_Calculate_IT(&hcordic, input_data, output_data, 4);

/* Wait for the calculation complete callback:
   HAL_CORDIC_CalculateCpltCallback() */
#define INPUT_BUFFER_SIZE 4U
#define OUTPUT_BUFFER_SIZE 4U

int32_t input_data[INPUT_BUFFER_SIZE] =  {0x80000000, 0x90000000, 0xA0000000, 0xB0000000};
int32_t output_data[OUTPUT_BUFFER_SIZE] = {0U};

hal_cordic_buffer_desc_t input_buffer = {
    .p_data = input_data,
    .size_word = INPUT_BUFFER_SIZE};

hal_cordic_buffer_desc_t output_buffer = {
    .p_data = output_data,
    .size_word = OUTPUT_BUFFER_SIZE};

hal_cordic_handle_t hcordic;
hal_cordic_config_t cordic_config;


HAL_CORDIC_Init(&hcordic, HAL_CORDIC);

HAL_RCC_CORDIC_EnableClock();

cordic_config.function   = HAL_CORDIC_FUNCTION_SINE;
cordic_config.precision  = HAL_CORDIC_PRECISION_6_CYCLE;
cordic_config.scaling_factor = HAL_CORDIC_SCALING_FACTOR_0;
cordic_config.nb_args    = HAL_CORDIC_NB_ARG_1;
cordic_config.nb_results = HAL_CORDIC_NB_RESULT_1;
cordic_config.in_width    = HAL_CORDIC_IN_WIDTH_32_BIT;
cordic_config.out_width   = HAL_CORDIC_OUT_WIDTH_32_BIT;

HAL_CORDIC_SetConfig(&hcordic,&cordic_config);

HAL_CORTEX_NVIC_SetPriority(CORDIC_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
HAL_CORTEX_NVIC_EnableIRQ(CORDIC_IRQn);

HAL_CORDIC_Calculate_IT(&hcordic, &input_buffer, &output_buffer);

/* Wait for the calculation complete callback:
   HAL_CORDIC_CalculateCpltCallback() */

Key changes

  1. HAL2 uses buffer descriptors (hal_cordic_buffer_desc_t) for inputs and outputs instead of raw pointers.

  2. HAL2 uses HAL_CORTEX_NVIC_SetPriority() and HAL_CORTEX_NVIC_EnableIRQ() for NVIC configuration.

  3. HAL2 explicitly enables the peripheral clock using HAL_RCC_CORDIC_EnableClock().

Related examples in HAL2

Example name

Brief

example_hal_cordic_sincos_it

This example illustrates configuring the CORDIC unit via the HAL API to calculate sine and cosine of an array of angles using interrupt mode.


Use case: HAL CORDIC calculate in DMA mode

Sequence diagram

CORDIC calculation in DMA mode

  @startuml

  participant "User application\n(thread mode)" as appli
  participant "<b>HAL CORDIC</b>" as cordic
  participant "<b>HAL DMA</b>" as dma
  participant "DMA IRQ handler" as dma_isr

  == Initialization / configuration ==
  appli -> cordic : HAL_CORDIC_Init(&hcordic)
  appli -> cordic : HAL_CORDIC_Configure(&hcordic, &cordic_config)
  appli -> dma : HAL_DMA_Init(hGPDMAx_CH0)\n(request: CORDIC_WRITE)
  appli -> dma : HAL_DMA_Init(hGPDMAx_CH1)\n(request: CORDIC_READ)
  appli -> cordic : __HAL_LINKDMA(hcordic, hdmaIn, hGPDMAx_CH0)\n__HAL_LINKDMA(hcordic, hdmaOut, hGPDMAx_CH1)

  == Calculation ==
  appli -> cordic : HAL_CORDIC_Calculate_DMA(&hcordic, input_data, output_data, n, CORDIC_DMA_DIR_IN_OUT)
  cordic --> appli : HAL status

  == DMA IRQ / callbacks ==
  dma_isr -> dma : DMAx_IRQHandler()\nHAL_DMA_IRQHandler(...)
  dma -> cordic : DMA callbacks
  cordic -> appli : HAL_CORDIC_CalculateCpltCallback(&hcordic)\n/ HAL_CORDIC_ErrorCallback(&hcordic)

  @enduml

Code snippet

HAL1

HAL2

 #define INPUT_BUFFER_SIZE 4U
 #define OUTPUT_BUFFER_SIZE 4U

 int32_t input_data[INPUT_BUFFER_SIZE] =  {0x80000000, 0x90000000, 0xA0000000, 0xB0000000};
 int32_t output_data[OUTPUT_BUFFER_SIZE] = {0U};









 CORDIC_HandleTypeDef hcordic;
 DMA_HandleTypeDef hGPDMA1_CH0;
 DMA_HandleTypeDef hGPDMA1_CH1;
 CORDIC_ConfigTypeDef cordic_config;

 hcordic.Instance = CORDIC;
 HAL_CORDIC_Init(&hcordic);

__HAL_RCC_CORDIC_CLK_ENABLE();

 cordic_config.Function         = CORDIC_FUNCTION_SINE;
 cordic_config.Precision        = CORDIC_PRECISION_6CYCLES;
 cordic_config.Scale            = CORDIC_SCALE_0;
 cordic_config.NbWrite          = CORDIC_NBWRITE_1;
 cordic_config.NbRead           = CORDIC_NBREAD_1;
 cordic_config.InSize           = CORDIC_INSIZE_32BITS;
 cordic_config.OutSize          = CORDIC_OUTSIZE_32BITS;

 HAL_CORDIC_Configure(&hcordic, &cordic_config)

__HAL_RCC_GPDMA1_CLK_ENABLE();

hGPDMA1_CH0.Instance = GPDMA1_Channel0;
hGPDMA1_CH0.Init.Request = GPDMA1_REQUEST_CORDIC_WRITE;
hGPDMA1_CH0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
hGPDMA1_CH0.Init.Direction = DMA_MEMORY_TO_PERIPH;
hGPDMA1_CH0.Init.SrcInc = DMA_SINC_INCREMENTED;
hGPDMA1_CH0.Init.DestInc = DMA_DINC_FIXED;
hGPDMA1_CH0.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
hGPDMA1_CH0.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
hGPDMA1_CH0.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
hGPDMA1_CH0.Init.SrcBurstLength = 1;
hGPDMA1_CH0.Init.DestBurstLength = 1;
hGPDMA1_CH0.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
hGPDMA1_CH0.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
hGPDMA1_CH0.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&hGPDMA1_CH0);

HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);

__HAL_LINKDMA(hcordic, hdmaIn, hGPDMA1_CH0);

__HAL_RCC_GPDMA1_CLK_ENABLE();

hGPDMA1_CH1.Instance = GPDMA1_Channel1;
hGPDMA1_CH1.Init.Request = GPDMA1_REQUEST_CORDIC_READ;
hGPDMA1_CH1.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
hGPDMA1_CH1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hGPDMA1_CH1.Init.SrcInc = DMA_SINC_FIXED;
hGPDMA1_CH1.Init.DestInc = DMA_DINC_INCREMENTED;
hGPDMA1_CH1.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
hGPDMA1_CH1.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
hGPDMA1_CH1.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
hGPDMA1_CH1.Init.SrcBurstLength = 1;
hGPDMA1_CH1.Init.DestBurstLength = 1;
hGPDMA1_CH1.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
hGPDMA1_CH1.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
hGPDMA1_CH1.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&hGPDMA1_CH1);

HAL_NVIC_SetPriority(GPDMA1_Channel1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel1_IRQn);

__HAL_LINKDMA(hcordic, hdmaOut, hGPDMA1_CH1);

 HAL_CORDIC_Calculate_DMA(&hcordic, input_data, output_data, 4, CORDIC_DMA_DIR_IN_OUT);

 /* Wait for the callbacks:
    HAL_CORDIC_CalculateCpltCallback()

    HAL_CORDIC_ErrorCallback() */
#define INPUT_BUFFER_SIZE 4U
#define OUTPUT_BUFFER_SIZE 4U

int32_t input_data[INPUT_BUFFER_SIZE] =  {0x80000000, 0x90000000, 0xA0000000, 0xB0000000};
int32_t output_data[OUTPUT_BUFFER_SIZE] = {0U};

hal_cordic_buffer_desc_t input_buffer = {
    .p_data = input_data,
    .size_word = INPUT_BUFFER_SIZE};

hal_cordic_buffer_desc_t output_buffer = {
    .p_data = output_data,
    .size_word = OUTPUT_BUFFER_SIZE};

hal_cordic_handle_t hcordic;
hal_dma_handle_t hLPDMA1_CH0;
hal_dma_handle_t hLPDMA1_CH1;
hal_cordic_config_t cordic_config;


HAL_CORDIC_Init(&hcordic, HAL_CORDIC);

HAL_RCC_CORDIC_EnableClock();

cordic_config.function   = HAL_CORDIC_FUNCTION_SINE;
cordic_config.precision  = HAL_CORDIC_PRECISION_6_CYCLE;
cordic_config.scaling_factor  = HAL_CORDIC_SCALING_FACTOR_0;
cordic_config.nb_args    = HAL_CORDIC_NB_ARG_1;
cordic_config.nb_results = HAL_CORDIC_NB_RESULT_1;
cordic_config.in_width    = HAL_CORDIC_IN_WIDTH_32_BIT;
cordic_config.out_width   = HAL_CORDIC_OUT_WIDTH_32_BIT;

HAL_CORDIC_SetConfig(&hcordic,&cordic_config);

HAL_RCC_LPDMA1_EnableClock();

HAL_DMA_Init(&hLPDMA1_CH0, HAL_LPDMA1_CH0);




hal_dma_direct_xfer_config_t xfer_cfg_cordic_wr_dma;
xfer_cfg_cordic_wr_dma.request         = HAL_LPDMA1_REQUEST_CORDIC_WR;
xfer_cfg_cordic_wr_dma.direction       = HAL_DMA_DIRECTION_MEMORY_TO_PERIPH;
xfer_cfg_cordic_wr_dma.src_inc         = HAL_DMA_SRC_ADDR_INCREMENTED;
xfer_cfg_cordic_wr_dma.dest_inc        = HAL_DMA_DEST_ADDR_FIXED;
xfer_cfg_cordic_wr_dma.src_data_width  = HAL_DMA_SRC_DATA_WIDTH_WORD;
xfer_cfg_cordic_wr_dma.dest_data_width = HAL_DMA_DEST_DATA_WIDTH_WORD;
xfer_cfg_cordic_wr_dma.priority        = HAL_DMA_PRIORITY_LOW_WEIGHT_LOW;

HAL_DMA_SetConfigPeriphDirectXfer(&hLPDMA1_CH0, &xfer_cfg_cordic_wr_dma);

HAL_CORTEX_NVIC_SetPriority(LPDMA1_CH0_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
HAL_CORTEX_NVIC_EnableIRQ(LPDMA1_CH0_IRQn);

HAL_CORDIC_SetWriteDMA(&hCORDIC, &hLPDMA1_CH0);

HAL_RCC_LPDMA1_EnableClock();

HAL_DMA_Init(&hLPDMA1_CH1, HAL_LPDMA1_CH1);




hal_dma_direct_xfer_config_t xfer_cfg_cordic_rd_dma;
xfer_cfg_cordic_rd_dma.request         = HAL_LPDMA1_REQUEST_CORDIC_RD;
xfer_cfg_cordic_rd_dma.direction       = HAL_DMA_DIRECTION_PERIPH_TO_MEMORY;
xfer_cfg_cordic_rd_dma.src_inc         = HAL_DMA_SRC_ADDR_FIXED;
xfer_cfg_cordic_rd_dma.dest_inc        = HAL_DMA_DEST_ADDR_INCREMENTED;
xfer_cfg_cordic_rd_dma.src_data_width  = HAL_DMA_SRC_DATA_WIDTH_WORD;
xfer_cfg_cordic_rd_dma.dest_data_width = HAL_DMA_DEST_DATA_WIDTH_WORD;
xfer_cfg_cordic_rd_dma.priority        = HAL_DMA_PRIORITY_LOW_WEIGHT_LOW;

HAL_DMA_SetConfigPeriphDirectXfer(&hLPDMA1_CH1, &xfer_cfg_cordic_rd_dma);

HAL_CORTEX_NVIC_SetPriority(LPDMA1_CH1_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
HAL_CORTEX_NVIC_EnableIRQ(LPDMA1_CH1_IRQn);

HAL_CORDIC_SetReadDMA(&hCORDIC, &hLPDMA1_CH1);

HAL_CORDIC_Calculate_DMA(&hcordic, &input_buffer, &output_buffer);

/* Wait for the callbacks:
   HAL_CORDIC_CalculateCpltCallback()
   HAL_CORDIC_WriteCpltCallback()
   HAL_CORDIC_ErrorCallback() */

Key changes

  1. HAL2 configures CORDIC DMA channels explicitly using HAL_CORDIC_SetWriteDMA() and HAL_CORDIC_SetReadDMA().

  2. HAL2 uses hal_dma_direct_xfer_config_t and HAL_DMA_SetConfigPeriphDirectXfer() to configure DMA transfers.

  3. HAL2 introduces additional callbacks for split DMA streams (for example, HAL_CORDIC_WriteCpltCallback()).

Related examples in HAL2

Example name

Brief

example_hal_cordic_sincos_dma

This example illustrates configuring the CORDIC unit via the HAL API to calculate sine and cosine of an array of angles using DMA for efficient data transfer.


layout :

large_read_area

Use case: HAL CORDIC calculation in DMA mode with peripheral (ADC)

In HAL1, to use the CORDIC peripheral together with another peripheral (such as ADC, Timer, etc.) in DMA mode, you can configure the DMA direction as follows:

CORDIC_DMA_DIR_IN or CORDIC_DMA_DIR_OUT enables one-sided stream management by the CORDIC peripheral. CORDIC_DMA_DIR_NONE allows two peripherals to write to and read from CORDIC data registers.

In HAL2, the new functions HAL_CORDIC_Write_DMA() and HAL_CORDIC_Read_DMA() handle DMA write and read operations separately for improved peripheral management.

In this use case, the ADC performs sampling, conversion, and writes the result directly to the CORDIC WDATA register using DMA. The CORDIC peripheral then reads only the result. In HAL1, one-way stream management is implemented by setting the DMA direction argument to CORDIC_DMA_DIR_OUT. In HAL2, the read stream is managed using HAL_CORDIC_Read_DMA() instead.

Sequence diagram

ADC-to-CORDIC streaming with DMA (CORDIC output only)

  @startuml

  participant "User application\n(thread mode)" as appli
  participant "<b>HAL ADC</b>" as adc
  participant "<b>HAL CORDIC</b>" as cordic
  participant "<b>HAL DMA</b>" as dma
  participant "DMA IRQ handler" as dma_isr

  == Initialization / configuration ==
  appli -> adc : HAL_ADC_Init(...)\nHAL_ADC_ConfigChannel(...)
  appli -> cordic : HAL_CORDIC_Init(&hcordic)\nHAL_CORDIC_Configure(&hcordic, &cordic_config)
  appli -> dma : HAL_DMA_Init(ADC DMA)\nHAL_DMA_Init(CORDIC READ DMA)

  == Start streams ==
  appli -> cordic : HAL_CORDIC_Calculate_DMA(&hcordic, NULL, output_data, n, CORDIC_DMA_DIR_OUT)
  appli -> appli : write_addr = &CORDIC->WDATA
  appli -> adc : HAL_ADC_Start_DMA(&hadc, (uint32_t*)write_addr, n)

  == DMA IRQ / callbacks ==
  dma_isr -> dma : DMAx_IRQHandler()\nHAL_DMA_IRQHandler(...)
  dma -> adc : ADC DMA callbacks
  dma -> cordic : CORDIC DMA callbacks
  cordic -> appli : HAL_CORDIC_CalculateCpltCallback(...)\n/ HAL_CORDIC_ErrorCallback(...)
  adc -> appli : HAL_ADC_ConvCpltCallback(...)\n/ HAL_ADC_ErrorCallback(...)

  @enduml

Code snippet

HAL1

HAL2

#define ADC_CONVERTED_DATA_BUFFER_SIZE   ((uint32_t)  32)


ADC_HandleTypeDef hadc4;
DMA_HandleTypeDef handle_GPDMA1_Channel10;
CORDIC_HandleTypeDef hcordic;
DMA_HandleTypeDef handle_GPDMA1_Channel0;



static int32_t output_data[32];
uint32_t  write_addr;




ADC_ChannelConfTypeDef sConfig = {0};

hadc4.Instance = ADC4;
hadc4.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4;
hadc4.Init.Resolution = ADC_RESOLUTION_12B;
hadc4.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc4.Init.ScanConvMode = ADC4_SCAN_DISABLE;
hadc4.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc4.Init.LowPowerAutoPowerOff = ADC_LOW_POWER_NONE;
hadc4.Init.LowPowerAutoWait = DISABLE;
hadc4.Init.ContinuousConvMode = ENABLE;
hadc4.Init.NbrOfConversion = 1;
hadc4.Init.DiscontinuousConvMode = DISABLE;
hadc4.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc4.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc4.Init.DMAContinuousRequests = ENABLE;
hadc4.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_LOW;
hadc4.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc4.Init.SamplingTimeCommon1 = ADC4_SAMPLETIME_79CYCLES_5;
hadc4.Init.SamplingTimeCommon2 = ADC4_SAMPLETIME_79CYCLES_5;
hadc4.Init.OversamplingMode = DISABLE;
HAL_ADC_Init(&hadc4);

sConfig.Channel = ADC_CHANNEL_4;
sConfig.Rank = ADC4_REGULAR_RANK_1;
sConfig.SamplingTime = ADC4_SAMPLINGTIME_COMMON_1;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
HAL_ADC_ConfigChannel(&hadc4, &sConfig);












__HAL_RCC_GPDMA1_CLK_ENABLE();

handle_GPDMA1_Channel10.Instance = GPDMA1_Channel10;
handle_GPDMA1_Channel10.Init.Request = GPDMA1_REQUEST_ADC4;
handle_GPDMA1_Channel10.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel10.Init.Direction = DMA_PERIPH_TO_MEMORY;
handle_GPDMA1_Channel10.Init.SrcInc = DMA_SINC_FIXED;
handle_GPDMA1_Channel10.Init.DestInc = DMA_DINC_FIXED;
handle_GPDMA1_Channel10.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
handle_GPDMA1_Channel10.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
handle_GPDMA1_Channel10.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel10.Init.SrcBurstLength = 1;
handle_GPDMA1_Channel10.Init.DestBurstLength = 1;
handle_GPDMA1_Channel10.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
handle_GPDMA1_Channel10.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel10.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&handle_GPDMA1_Channel10);

HAL_NVIC_SetPriority(GPDMA1_Channel0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel0_IRQn);

__HAL_LINKDMA(hadc, DMA_Handle, handle_GPDMA1_Channel10);

__HAL_RCC_GPIOC_CLK_ENABLE();

GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

hcordic.Instance = CORDIC;
HAL_CORDIC_Init(&hcordic);

CORDIC_ConfigTypeDef cordic_config;
cordic_config.Function         = CORDIC_FUNCTION_SINE;
cordic_config.Precision        = CORDIC_PRECISION_6CYCLES;
cordic_config.Scale            = CORDIC_SCALE_0;
cordic_config.NbWrite          = CORDIC_NBWRITE_1;
cordic_config.NbRead           = CORDIC_NBREAD_1;
cordic_config.InSize           = CORDIC_INSIZE_32BITS;
cordic_config.OutSize          = CORDIC_OUTSIZE_32BITS;
HAL_CORDIC_Configure(&hcordic, &cordic_config);


__HAL_RCC_GPDMA1_CLK_ENABLE()

handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0;
handle_GPDMA1_Channel0.Init.Request = GPDMA1_REQUEST_CORDIC_READ;
handle_GPDMA1_Channel0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel0.Init.Direction = DMA_PERIPH_TO_MEMORY;
handle_GPDMA1_Channel0.Init.SrcInc = DMA_SINC_FIXED;
handle_GPDMA1_Channel0.Init.DestInc = DMA_DINC_INCREMENTED;
handle_GPDMA1_Channel0.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
handle_GPDMA1_Channel0.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
handle_GPDMA1_Channel0.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel0.Init.SrcBurstLength = 1;
handle_GPDMA1_Channel0.Init.DestBurstLength = 1;
handle_GPDMA1_Channel0.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
handle_GPDMA1_Channel0.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel0.Init.Mode = DMA_NORMAL;
HAL_DMA_Init(&handle_GPDMA1_Channel0);

HAL_NVIC_SetPriority(GPDMA1_Channel10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel10_IRQn);

__HAL_LINKDMA(hcordic, hdmaOut, handle_GPDMA1_Channel0);

/* pInBuff is set to NULL as the input data stream to the CORDIC WDATA register will be handled by the ADC,
   DMADirection is set to CORDIC_DMA_DIR_OUT as HAL_CORDIC will handle only the output data stream */
HAL_CORDIC_Calculate_DMA(&hcordic, NULL, output_data, (ADC_CONVERTED_DATA_BUFFER_SIZE), CORDIC_DMA_DIR_OUT);

write_addr = (uint32_t) &(CORDIC->WDATA);


/* pData = (uint32_t *)write_addr: ADC converted values written directly to the CORDIC WDATA register */
HAL_ADC_Start_DMA(&hadc4, (uint32_t *)write_addr, (ADC_CONVERTED_DATA_BUFFER_SIZE));

/* Wait for the callbacks:
   HAL_ADC_ConvCpltCallback
   HAL_ADC_ErrorCallback
   HAL_CORDIC_CalculateCpltCallback
   HAL_CORDIC_ErrorCallback*/
#define OUTPUT_BUFFER_SIZE   ((uint32_t)  32)

ADC_TypeDef *instance = ADC1;
hal_adc_handle_t hADC1;
hal_dma_handle_t hGPDMA1_CH0;
hal_cordic_handle_t hCORDIC;
hal_dma_handle_t hGPDMA1_CH1;
hal_adc_config_t adc_config;
hal_adc_inj_config_t adc_inj_config;

static int32_t output_data[32];
static volatile uint32_t *write_addr;
hal_cordic_buffer_desc_t output_buffer = {
  .p_data = output_data,
  .size_word = OUTPUT_BUFFER_SIZE};

HAL_ADC_Init(&hADC1, HAL_ADC1);

hal_adc_config_t adc_config;
adc_config.clock               = HAL_ADC_CLOCK_ASYNC_DIV4;
adc_config.resolution          = HAL_ADC_RESOLUTION_14_BIT;
adc_config.trigger_freq_mode   = HAL_ADC_TRIGGER_FREQ_HIGH;
adc_config.sampling_mode       = HAL_ADC_SAMPLING_MODE_NORMAL;
adc_config.sampling_time_com1 = HAL_ADC_SAMPLING_TIME_814CYCLES_5;
adc_config.sampling_time_com2 = HAL_ADC_SAMPLING_TIME_814CYCLES_5;
HAL_ADC_SetConfig(&hADC1, &adc_config);

hal_adc_reg_config_t reg_config;
reg_config.trigger_src        = HAL_ADC_REG_TRIG_SOFTWARE_START;
reg_config.trigger_edge       = HAL_ADC_REG_TRIG_EDGE_NONE;
reg_config.sequencer_length   = 1;
reg_config.sequencer_discont  = HAL_ADC_REG_SEQ_DISCONT_DISABLE;
reg_config.continuous         = HAL_ADC_REG_CONV_CONTINUOUS;
reg_config.overrun            = HAL_ADC_REG_OVR_DATA_OVERWRITTEN;
reg_config.data_transfer      = HAL_ADC_REG_DATA_TRANSFER_NONE;
reg_config.sequencer_mode      = HAL_ADC_REG_SEQ_FIXED;
HAL_ADC_REG_SetConfig(&hADC1, &reg_config);


hal_adc_channel_config_t adc_channel_config;
adc_channel_config.group           = HAL_ADC_GROUP_REGULAR;
adc_channel_config.sequencer_rank  = 1;
adc_channel_config.input_mode      = HAL_ADC_IN_SINGLE_ENDED;
adc_channel_config.sampling_time   = HAL_ADC_SAMPLING_TIME_814CYCLES;
HAL_ADC_SetConfigChannel(&hADC1, HAL_ADC_CHANNEL_4, &adc_channel_config);

hal_adc_inj_config_t adc_inj_config;
adc_inj_config.trigger_src = HAL_ADC_INJ_TRIG_SOFTWARE_START;
adc_inj_config.trigger_edge = HAL_ADC_INJ_TRIG_EDGE_NONE;
adc_inj_config.sequencer_length = 1;
adc_inj_config.sequencer_discont = HAL_ADC_INJ_SEQ_DISCONT_DISABLE;
HAL_ADC_INJ_SetConfig(&hADC1, &adc_inj_config);

adc_channel_config.group           = HAL_ADC_GROUP_INJECTED;
HAL_ADC_SetConfigChannel(&hADC1, HAL_ADC_CHANNEL_4 , &adc_channel_config);

HAL_RCC_GPDMA1_EnableClock();

HAL_DMA_Init(&hGPDMA1_CH0, HAL_GPDMA1_CH0);

hal_dma_direct_xfer_config_t xfer_cfg_adc1_dma;
xfer_cfg_adc1_dma.request         = HAL_GPDMA1_REQUEST_ADC1;
xfer_cfg_adc1_dma.direction       = HAL_DMA_DIRECTION_PERIPH_TO_MEMORY;
xfer_cfg_adc1_dma.src_inc         = HAL_DMA_SRC_ADDR_FIXED;
xfer_cfg_adc1_dma.dest_inc        = HAL_DMA_DEST_ADDR_FIXED;
xfer_cfg_adc1_dma.src_data_width  = HAL_DMA_SRC_DATA_WIDTH_WORD;
xfer_cfg_adc1_dma.dest_data_width = HAL_DMA_DEST_DATA_WIDTH_WORD;
xfer_cfg_adc1_dma.priority        = HAL_DMA_PRIORITY_LOW_WEIGHT_LOW;
HAL_DMA_SetConfigPeriphDirectXfer(&hGPDMA1_CH0, &xfer_cfg_adc1_dma);




HAL_CORTEX_NVIC_SetPriority(GPDMA1_CH0_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
HAL_CORTEX_NVIC_EnableIRQ(GPDMA1_CH0_IRQn);

HAL_ADC_REG_SetDMA(&hADC1, &hGPDMA1_CH0);

HAL_RCC_GPIOC_EnableClock();

hal_gpio_config_t  gpio_config;
gpio_config.mode        = HAL_GPIO_MODE_ANALOG;
gpio_config.pull        = HAL_GPIO_PULL_NO;
HAL_GPIO_Init(HAL_GPIOC, HAL_GPIO_PIN_3, &gpio_config);

hal_cordic_config_t cordic_config;
HAL_CORDIC_Init(&hCORDIC, HAL_CORDIC);

HAL_RCC_CORDIC_EnableClock();

cordic_config.function       = LL_CORDIC_FUNCTION_MODULUS;
cordic_config.in_width       = HAL_CORDIC_IN_WIDTH_32_BIT;
cordic_config.nb_arg         = HAL_CORDIC_NB_ARG_1;
cordic_config.out_width      = HAL_CORDIC_OUT_WIDTH_32_BIT;
cordic_config.nb_result      = HAL_CORDIC_NB_RESULT_1;
cordic_config.scaling_factor = HAL_CORDIC_SCALING_FACTOR_0;
cordic_config.precision      = HAL_CORDIC_PRECISION_5_CYCLE;
HAL_CORDIC_SetConfig(&hCORDIC,&cordic_config);

HAL_RCC_GPDMA1_EnableClock();

HAL_DMA_Init(&hGPDMA1_CH1, HAL_GPDMA1_CH1);

hal_dma_direct_xfer_config_t xfer_cfg_cordic_rd_dma;
xfer_cfg_cordic_rd_dma.request         = HAL_GPDMA1_REQUEST_CORDIC_RD;
xfer_cfg_cordic_rd_dma.direction       = HAL_DMA_DIRECTION_PERIPH_TO_MEMORY;
xfer_cfg_cordic_rd_dma.src_inc         = HAL_DMA_SRC_ADDR_FIXED;
xfer_cfg_cordic_rd_dma.dest_inc        = HAL_DMA_DEST_ADDR_INCREMENTED;
xfer_cfg_cordic_rd_dma.src_data_width  = HAL_DMA_SRC_DATA_WIDTH_WORD;
xfer_cfg_cordic_rd_dma.dest_data_width = HAL_DMA_DEST_DATA_WIDTH_WORD;
xfer_cfg_cordic_rd_dma.priority        = HAL_DMA_PRIORITY_LOW_WEIGHT_LOW;
HAL_DMA_SetConfigPeriphDirectXfer(&hGPDMA1_CH1, &xfer_cfg_cordic_rd_dma);




HAL_CORTEX_NVIC_SetPriority(GPDMA1_CH1_IRQn, HAL_CORTEX_NVIC_PREEMP_PRIORITY_0, HAL_CORTEX_NVIC_SUB_PRIORITY_0);
HAL_CORTEX_NVIC_EnableIRQ(GPDMA1_CH1_IRQn);

HAL_CORDIC_SetReadDMA(&hCORDIC, &hGPDMA1_CH1);


/* Start reading the CORDIC output in DMA mode, while the input stream is handled by HAL_ADC */
HAL_CORDIC_Read_DMA(&hCORDIC, &output_buffer);

write_addr = HAL_CORDIC_GetWriteAddress(&hCORDIC);

HAL_ADC_Start(hADC);
/* p_data = (uint8_t const *)write_addr: ADC converted values written directly to the CORDIC WDATA register */
HAL_ADC_REG_StartConv_DMA(hADC, (uint8_t const *)write_addr, OUTPUT_BUFFER_SIZE*4);

/* Wait for the callbacks:
   HAL_ADC_REG_DataTransferCpltCallback
   HAL_ADC_ErrorCallback
   HAL_CORDIC_CalculateCpltCallback()
   HAL_CORDIC_ErrorCallback() */

Similarly to this use case, when using the CORDIC peripheral with a DAC in HAL1, the function HAL_CORDIC_Calculate_DMA is used with the CORDIC_DMA_DIR_IN argument. In HAL2, this is replaced by HAL_CORDIC_Write_DMA().

Key changes

  1. HAL2 splits DMA stream management with dedicated APIs: HAL_CORDIC_Write_DMA() and HAL_CORDIC_Read_DMA().

  2. HAL2 provides HAL_CORDIC_GetWriteAddress() to let another peripheral (such as ADC) write directly to the CORDIC input register.

  3. HAL2 configures the CORDIC DMA streams explicitly using HAL_CORDIC_SetReadDMA() (and HAL_CORDIC_SetWriteDMA() when needed).

Related examples in HAL2

No related example is listed in this document for this use case.